using System;
using System.Collections.Generic;
using System.Text;
using MacomberMap.Common.User_Interfaces.Components;
using System.Xml;
using System.Data.Common;
using System.ComponentModel;
using MacomberMap.Common.Internals;
using MacomberMap.Common.Types;
using MacomberMap.Common.Convertors;
using System.Drawing;
using MacomberMap.Common.Logging;
using MacomberMap.Common.Events;
using System.Windows.Forms;

namespace MacomberMap.Common.Components
{
    /// <summary>
    /// This class holds information on a line
    /// </summary>
    [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.Both)]    
    public class MM_Line : MM_Element
    {

        #region Variable declarations
        /// <summary>
        /// Whether the line is connected to a series compensator
        /// </summary>
        [Category("Connections"), Description("Whether the line is connected to a series compensator"), DefaultValue(false), MM_Serializable_Target(MM_Serializable_Target.enumTargetType.TypeCollection)]
        public bool IsSeriesCompensator
        {
            get { return _IsSeriesCompensator; }
            set { _IsSeriesCompensator = value; }
        }
        private bool _IsSeriesCompensator = false;

        /// <summary>
        /// Whether the line is connected to a Multiple Segment
        /// </summary>
        [Category("Connections"), Description("Whether the line is connected to a Multiple Segment"), DefaultValue(false), MM_Serializable_Target(MM_Serializable_Target.enumTargetType.TypeCollection)]
        public bool IsMultipleSegment
        {
            get { return _IsMultipleSegment; }
            set { _IsMultipleSegment = value; }
        }
        private bool _IsMultipleSegment = false;


        /// <summary>
        /// The TEID of the line (not segment or series compensator
        /// </summary>
        [Category("Connections"), Description("The TEID of the line (not segment or series compensator"), MM_Serializable_Target(MM_Serializable_Target.enumTargetType.TypeCollection)]        
        public UInt64 LineTEID
        {
            get { return _LineTEID; }
            set { _LineTEID = value; }
        }
        private UInt64 _LineTEID;

        /// <summary>The substations to which the line is connected</summary>
        public MM_Substation[] ConnectedStations = new MM_Substation[2];               

        /// <summary>The line routing coordinates</summary>
        [Category("Connections"), Description("The routing inflection points for the line"), MM_Serializable_Target(MM_Serializable_Target.enumTargetType.TypeCollection)]
        public PointF[] Coordinates
        {
            get
            {
                if (_Coordinates == null)
                    _Coordinates = new PointF[] { Substation1.LatLong, Substation2.LatLong };
                return _Coordinates;
            }
            set { _Coordinates = value; }
        }
        private PointF[] _Coordinates = null;

        #endregion

        #region Variable interfaces
        /// <summary>
        /// Override the substation definition so it's not serialized
        /// </summary>
        [MM_Serializable_Target(MM_Serializable_Target.enumTargetType.None)]
        public new MM_Substation Substation
        {
            get { return null; }
        }

        /// <summary>
        /// The first substation to which the line is connected
        /// </summary>
        [Category("Connections"), Description("The first substation to which the line is connected"), TypeConverter(typeof(MM_Substation_Locator)), MM_Serializable_Target(MM_Serializable_Target.enumTargetType.TypeCollection)]
        public MM_Substation Substation1
        {
            get { return ConnectedStations[0]; }
            set { ConnectedStations[0] = value; }
        }

        /// <summary>
        /// The second substation to which the line is connected
        /// </summary>
        [Category("Connections"), Description("The second substation to which the line is connected"), TypeConverter(typeof(MM_Substation_Locator)), MM_Serializable_Target(MM_Serializable_Target.enumTargetType.TypeCollection)]
        public MM_Substation Substation2
        {
            get { return ConnectedStations[1]; }
            set { ConnectedStations[1] = value; }
        }       

       

        /// <summary>Return the long name of the line (substation long name to substation long name)</summary>        
        public String LongName
        {
            get
            {
                if (Substation1 == null || Substation2 == null)
                    return "?";
                else
                    return Substation1.LongName + " to " + Substation2.LongName;
            }
        }


        /// <summary>
        /// Return the estimated length of the line
        /// </summary>
        public float Length
        {
            get
            {
                return Substation1.DistanceTo(Substation2);
            }
        }
        #endregion

        


        #region Initialization
        /// <summary>
        /// Create a new line
        /// </summary>
        /// <param name="BaseElement"></param>
        public MM_Line(XmlElement BaseElement)
        {
            this.ElemType = MM_Overall_Display.FindElementType("Line");
            this.Name = BaseElement.Attributes["Name"].Value;
            string[] splStation = BaseElement.Attributes["ConnectedStations"].Value.Split(',');
            this.Substation1 = MM_Repository.TEIDs[UInt64.Parse(splStation[0])] as MM_Substation;
            this.Substation2 = MM_Repository.TEIDs[UInt64.Parse(splStation[1])] as MM_Substation;
            this.TEID = UInt64.Parse(BaseElement.Attributes["TEID"].Value);
            this.KVLevel = MM_Overall_Display.KVLevels[BaseElement.Attributes["KVLevel"].Value];
            MM_Repository.Lines.Add(this.Name, this);
            if (!MM_Overall_Display.ElemTypes.TryGetValue("Line", out this.ElemType))
                MM_Overall_Display.ElemTypes.Add("Line", this.ElemType =new MM_Element_Type("Line","Ln","Line"));             
            MM_Repository.TEIDs.Add(this.TEID, this);
        }

        /// <summary>
        /// Create a new line from a database reader
        /// </summary>
        /// <param name="DataReader">The database reader containing the line's information</param>        
        public MM_Line(DbDataReader DataReader): base(DataReader)
        {                                           
            this.ElemType = MM_Overall_Display.ElemTypes["Line"];
        }


        /// <summary>
        /// Create an empty line
        /// </summary>
        public MM_Line()
        {
            this.ElemType = MM_Overall_Display.ElemTypes["Line"];
        }
        #endregion


        /// <summary>
        /// Return the line's long name
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (this.Substation1 != null && this.Substation2 != null)
                return ElemType.Name + " " + this.Name + " (" + this.Substation1.LongName + " to " + this.Substation2.LongName + " / " + this.TEID.ToString() + ")";
            else
                return ElemType.Name + " " + this.Name;
            
        }

        #region Menu building
        /// <summary>
        /// Add substation-specific items to the popup menu.
        /// </summary>
        /// <param name="MenuStrip"></param>
        public void AddMenuItems(ContextMenuStrip MenuStrip)
        {
            //TODO: Add permissions in
            MenuStrip.Items.Add(ElemType.Name + " " + this.Name);
            MenuStrip.Items.Add("  Between: " + (this as MM_Line).Substation1.LongName + " and " + (this as MM_Line).Substation2.LongName);
            if (Substation1.County == Substation2.County)
                MenuStrip.Items.Add("  County: " + Substation1.County.Name);
            else
            {
                MenuStrip.Items.Add("  Counties: between " + Substation1.County.Name + " and " + Substation2.County.Name);                
            }
            MenuStrip.Items.Add("  Est. Distance: " + Length.ToString("#,##0") + " miles");            
        }
        #endregion
    }
}
